﻿using System;
using System.Collections.Generic;
using System.Text;
using SharpCommunications.Logging;
using SharpCommunications.Connection;
using SharpCommunications.Interfaces;
using System.Threading;

namespace SharpCommunications.TestServer
{
    public delegate void ConnectionThreadTerminatedHandlerDelegate(ConnectionThread connectionThread);

    public class ConnectionThread : IDisposable
    {
        public event ConnectionThreadTerminatedHandlerDelegate Terminated;

        protected ISharpConnectionEndpoint connectionEndpoint;
        protected Thread thread;
        protected bool quit = false;

        protected Guid id = Guid.NewGuid();

        public ConnectionThread(ISharpConnectionEndpoint connectionEndpoint)
        {
            this.connectionEndpoint = connectionEndpoint;
            this.connectionEndpoint.ReceivedMessage += new ReceivedMessageHandlerDelegate(connectionEndpoint_ReceivedMessage);

            this.thread = new Thread(new ThreadStart(this.SendingThreadFunction));
            this.thread.IsBackground = true;
            this.thread.Name = "Connection Thread";
            this.thread.Start();
        }

        protected void SendingThreadFunction()
        {
            Location location = new Location("ConnectionThread.ThreadFunction()");

            try
            {
                this.connectionEndpoint.SendMessage(string.Format("{0}: Server message 1", this.id));
                Thread.Sleep(1000);

                this.connectionEndpoint.SendMessage(string.Format("{0}: Server message 2", this.id));
                Thread.Sleep(1000);

                this.connectionEndpoint.SendMessage(string.Format("{0}: Server message 3", this.id));
                Thread.Sleep(1000);

                while(!this.quit)
                {
                    Thread.Sleep(1000);
                }

                LogFactory.Log.InfoMessage(location, "Terminating");

                Close();

                if(this.Terminated != null)
                {
                    Terminated(this);
                }
            }
            catch (Exception ex)
            {
                LogFactory.Log.ErrorMessage(location, ex, true);
            }
        }

        void connectionEndpoint_ReceivedMessage(ISharpConnectionEndpoint connectionEndpoint, string message)
        {
            Location location = new Location("ConnectionThread.connectionEndpoint_ReceivedMessage()");

            if(message == "quit")
            {
                LogFactory.Log.InfoMessage(location, "{0}: RECEIVED: {1}", this.id, message);
                this.connectionEndpoint.SendMessage("SERVER: Connection Thread is quitting");
                this.quit = true;
            }
            else if(message.StartsWith("long message: "))
            {
                LogFactory.Log.InfoMessage(location, "{0}: RECEIVED: {1}", this.id, message.Substring(0, 50) + "...");
                this.connectionEndpoint.SendMessage(message);
            }
            else
            {
                LogFactory.Log.InfoMessage(location, "{0}: RECEIVED: {1}", this.id, message);
                this.connectionEndpoint.SendMessage(string.Format("{0}: Received: {1}", this.id, message));
            }
        }

        public void Close()
        {
            this.connectionEndpoint.Close();
        }

        #region IDisposable Members

        public void Dispose()
        {
            if(this.thread != null && !this.quit)
            {
                this.thread.Abort();
                this.thread = null;
            }

            Close();
        }

        #endregion

    }
}
